package main
import (
	"fmt"
	"reflect"
)
//反射的入门案例：
//（1）编写一个 对（基本数据类型，interface{}，reflect.Value）进行反射的基本操作！  ********
//（2）编写一个 对（结构体类型，interface{}，reflect.Value）进行反射的基本操作！

func main (){
	//1.先定义一个int
	// var num int = 100
	// reflectTest01(num)

	//2.定义一个student实例
	stu := Student{
		Name : "fmx",
		Age : 22,
	}
	reflectTest02(stu)
}


//专门演示反射
func reflectTest01(b interface{}){
	//通过反射获取传入的变量的type，kind，值
	//1.先获取到 reflect.Type 类型
	rType := reflect.TypeOf(b)   //rType 实质上是 Type类型，reflect下的Type类型，并非原先意义下的 int
	fmt.Printf("rType=%v, this type is :%T\n",rType,rType)


	//2.获取到 reflect.Value
	rValue := reflect.ValueOf(b)  //rValue 实质上是 Value类型，reflect下的Value类型,并非原先意义下的 100
	fmt.Printf("rValue=%v, this type is :%T\n",rValue,rValue)

	//n := 10 + rValue  // 这句话会把错，因为它不是一个简单的100，而实一个 reflect.Value类型! 虽然直接输出可以输出他的值
	n := 10 + rValue.Int()   //reflect.Value类型所绑定的方法!返回它的值
	fmt.Println("n :=",n)


	//3.将 rValue类型才行转成 interface{}
	iv := rValue.Interface()  //通过Interface方法将Value类型转成interface{}类型
	//将 interface{} 通过类型断言 转成所需要的类型
	num2 := iv.(int)
	fmt.Printf("num2= %v, this type is :%T\n",num2,num2)
}





//专用演示反射（对结构体的反射）
func reflectTest02(b interface{}){
	//通过反射获取传入的变量的type，kind，值
	//1.先获取到 reflect.Type 类型
	rTyp := reflect.TypeOf(b)   //rType 实质上是 Type类型，reflect下的Type类型，并非原先意义下的 类型
	fmt.Printf("rType=%v, this type is :%T\n",rTyp,rTyp)


	//2.获取到 reflect.Value
	rVal := reflect.ValueOf(b)  //rValue 实质上是 Value类型，reflect下的Value类型,并非原先意义下的 值
	fmt.Printf("rValue=%v, this type is :%T\n",rVal,rVal)

	//3.将 rValue类型才行转成 interface{}
	iV := rVal.Interface()  //通过Interface方法将Value类型转成interface{}类型
	fmt.Printf("iv = %v , iv Type is :%T\n",iV,iV)  //iv = {fmx 22} , iv Type is :main.Student  iV是个指向这个Student类型的接口故会这样的结果，
	//但无法获取iV.Name因为编译器在编译的那一时刻就知道这个接口指向Student，但就是不知道iV.Name是什么，所以需要类型断言

	//将 interface{} 通过类型断言 转成所需要的类型
	stu,ok := iV.(Student)
	//更加灵活的做法就是 用 switch iV.(type)的断言形式来判断类型在进行转换类型
	if ok {
		fmt.Println("stu'Name : ",stu.Name)
	}

	//4.获取 变量对应的Kind（类别）
	fmt.Printf("b's Kind = %v\n",rVal.Kind())   //b's Kind = struct
	fmt.Printf("b's Kind = %v",rTyp.Kind()) 	 //b's Kind = struct
	//以上两个输出相同结果
}

type Student struct{
	Name string
	Age int
}